{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## _*H2 ground state energy computation using Quantum Phase Estimation*_\n",
    "\n",
    "This notebook demonstrates using Qiskit Chemistry to compute ground state energy of the Hydrogen (H2) molecule using QPE (Quantum Phase Estimation) algorithm. Let's look at how to carry out such computation programmatically.\n",
    "\n",
    "This notebook has been written to use the PYSCF chemistry driver."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We first set up the H2 molecule, create the fermionic and in turn the qubit operator using PySCF."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import OrderedDict\n",
    "import time\n",
    "\n",
    "from qiskit import BasicAer\n",
    "from qiskit.aqua import AquaError\n",
    "from qiskit.aqua import QuantumInstance\n",
    "from qiskit.aqua.operators import Z2Symmetries\n",
    "from qiskit.aqua.operators import op_converter\n",
    "from qiskit.aqua.algorithms import NumPyMinimumEigensolver, QPE\n",
    "from qiskit.circuit.library import QFT\n",
    "from qiskit.chemistry import FermionicOperator\n",
    "from qiskit.chemistry.components.initial_states import HartreeFock\n",
    "from qiskit.chemistry.drivers import PySCFDriver, UnitsType\n",
    "\n",
    "distance = 0.735\n",
    "driver = PySCFDriver(atom='H .0 .0 .0; H .0 .0 {}'.format(distance),\n",
    "                     unit=UnitsType.ANGSTROM, charge=0, spin=0, basis='sto3g')\n",
    "molecule = driver.run()\n",
    "\n",
    "qubit_mapping = 'parity'\n",
    "fer_op = FermionicOperator(h1=molecule.one_body_integrals, h2=molecule.two_body_integrals)\n",
    "qubit_op = Z2Symmetries.two_qubit_reduction(op_converter.to_weighted_pauli_operator(fer_op.mapping(map_type=qubit_mapping, threshold=1e-10)), 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using a classical exact eigenvalue solver, we can establish the reference groundtruth value of the ground state energy:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The exact ground state energy is: -1.8572750302023797\n"
     ]
    }
   ],
   "source": [
    "exact_eigensolver = NumPyMinimumEigensolver(qubit_op)\n",
    "result_ee = exact_eigensolver.run()\n",
    "reference_energy = result_ee.eigenvalue.real\n",
    "print('The exact ground state energy is: {}'.format(result_ee.eigenvalue.real))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we set up the QPE algorithm instance using the HartreeFock initial state and a standard inverse quantum fourier transform, and execute:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The ground state energy as computed by QPE is: -1.8571368753258861\n"
     ]
    }
   ],
   "source": [
    "num_particles = molecule.num_alpha + molecule.num_beta\n",
    "two_qubit_reduction = True\n",
    "num_orbitals = qubit_op.num_qubits + (2 if two_qubit_reduction else 0)\n",
    "\n",
    "num_time_slices = 1\n",
    "n_ancillae = 9\n",
    "\n",
    "state_in = HartreeFock(num_orbitals, num_particles, qubit_mapping,\n",
    "                        two_qubit_reduction)\n",
    "iqft = QFT(n_ancillae).inverse()\n",
    "\n",
    "qpe = QPE(qubit_op, state_in, iqft, num_time_slices, n_ancillae,\n",
    "          expansion_mode='suzuki',\n",
    "          expansion_order=2, shallow_circuit_concat=True)\n",
    "backend = BasicAer.get_backend('qasm_simulator')\n",
    "quantum_instance = QuantumInstance(backend, shots=100)\n",
    "result_qpe = qpe.run(quantum_instance)\n",
    "print('The ground state energy as computed by QPE is: {}'.format(result_qpe.eigenvalue.real))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As can be easily seen, the QPE computed energy is quite close to the groundtruth value we computed earlier."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
